package com.av.db.layer.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.av.db.dataobjects.Tarjeta;
import com.av.db.layer.interfaces.TarjetaLayer;
import com.av.exceptions.AvException;

/**
 * Clase que contiene la implementacion de funciones para la tabla de tarjetas
 * utilizando la tecnologia de Hibernate
 * 
 * @author Victor J Morales R
 * 
 */
public class TarjetaLayerImpl extends HibernateDaoSupport implements
		TarjetaLayer {

	private static Logger log = Logger.getLogger(TarjetaLayerImpl.class);

	/**
	 * Funcion que actualiza en la base de datos una tarjeta en especifo
	 */
	@Override
	public void actualizar(Tarjeta tarjeta) throws AvException {
		log.info("Inicio - actualizar(Tarjeta tarjeta)");
		log.debug("Id : " + tarjeta.getId());
		log.debug("Tarjeta : " + tarjeta.toString());

		if (tarjeta == null) {
			log.error("No se puede actualizar una tarjeta nula");
			throw new AvException("Tarjeta nula a ser actualizada");
		}

		if (tarjeta.getId() < 0) {
			log.error("No se puede actualizar una tarjeta con identificador "
					+ "invalido");
			throw new AvException("Tarjeta con identificador invalido a ser "
					+ "actualizado");
		}

		getHibernateTemplate().update(tarjeta);

		log.info("Fin - actualizar(Tarjeta tarjeta)");
	}// actualizar

	/**
	 * Funcion que agrega en la base de datos configura una nueva tarjeta
	 */
	@Override
	public void agregar(Tarjeta tarjeta) throws AvException {
		log.info("Inicio - agregar(Tarjeta tarjeta)");
		log.debug("Tarjeta : " + tarjeta.toString());

		if (tarjeta == null) {
			log.error("No se puede agregar una tarjeta nula");
			throw new AvException("Tarjeta nula a ser agregada");
		}

		getHibernateTemplate().save(tarjeta);

		log.info("Fin - agregar(Tarjeta tarjeta)");
	}// agregar

	/**
	 * Funcion que elimina una tarjeta especifica de la base de datos
	 * configurada
	 */
	@Override
	public void eliminar(Tarjeta tarjeta) throws AvException {
		log.info("Inicio - eliminar(Tarjeta tarjeta)");
		log.debug("Tarjeta : " + tarjeta.toString());

		if (tarjeta == null) {
			log.error("No se puede eliminar una tarjeta nula");
			throw new AvException("Tarjeta nula a ser eliminada");
		}

		if (tarjeta.getId() < 0) {
			log
					.error("No se puede eliminar una tarjeta con identificador negativo");
			throw new AvException("Identificador negativo");
		}

		getHibernateTemplate().delete(tarjeta);

		log.info("Fin - eliminar(Tarjeta tarjeta)");
	}// eliminar

	/**
	 * Funcion que obtiene una tarjeta de la base de datos configurada a partir
	 * de su identificador
	 */
	@Override
	public Tarjeta obtener(int id) {
		log.info("Inicio - obtener(int id)");
		log.debug("Id : " + id);

		if (id < 0) {
			log
					.warn("No se puede obtener una tarjeta con identificador negativo");
			return null;
		}

		Tarjeta tmp = getHibernateTemplate().get(Tarjeta.class, id);

		if (tmp != null) {
			log.debug("Tarjeta : " + tmp.toString());
		} else {
			log.debug("Tarjeta no encontrada");
		}

		log.info("Fin - obtener(int id)");

		return tmp;
	}// obtener

	/**
	 * Funcion que obtiene el conjunto de todas las tarjetas registradas en la
	 * base de datos configurada
	 */
	@Override
	public Tarjeta[] obtener() {
		log.info("Inicio - obtener()");

		List<?> l = getSession().createCriteria(Tarjeta.class)
				.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).addOrder(
						Order.asc(Tarjeta.ID)).list();

		Tarjeta[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Tarjeta[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtener()");

		return tmp;
	}// obtener

	/**
	 * Funcion que obtiene todos las tarjetas activas del sistema
	 */
	@Override
	public Tarjeta[] obtenerActivos() {
		log.info("Inicio - obtenerActivos()");

		List<?> l = getSession().createCriteria(Tarjeta.class).add(
				Restrictions.eq(Tarjeta.ACTIVO, true)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).addOrder(Order.asc(Tarjeta.ID))
				.list();

		Tarjeta[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Tarjeta[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtenerActivos()");

		return tmp;
	}// obtenerActivos

	/**
	 * Funcion que obtiene todas las tarjetas inactivas registradas en el
	 * sistema
	 */
	@Override
	public Tarjeta[] obtenerInactivos() {
		log.info("Inicio - obtenerActivos()");

		List<?> l = getSession().createCriteria(Tarjeta.class).add(
				Restrictions.eq(Tarjeta.ACTIVO, false)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).addOrder(Order.asc(Tarjeta.ID))
				.list();

		Tarjeta[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Tarjeta[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtenerActivos()");

		return tmp;
	}// obtenerInactivos

	/**
	 * Funcion que obtiene la primera tarjeta activa a partir de su codigo o
	 * numero de placa
	 */
	@Override
	public Tarjeta obtenerPorCodigoONumPlaca(String codigo, String numPlaca) {
		log
				.info("Inicio - obtenerPorCodigoONumPlaca(String codigo, String numPlaca)");
		log.debug("Codigo : " + codigo);
		log.debug("Num. de placa : " + numPlaca);

		if ((codigo == null || codigo.trim().length() < 0)
				&& (numPlaca == null || numPlaca.trim().length() < 0)) {
			log
					.error("El codigo y el num. de placa no pueden ser vacios o nulos");
			return null;
		}

		Criteria c = getSession().createCriteria(Tarjeta.class);

		if (codigo != null && codigo.trim().length() > 0) {
			c.add(Restrictions.eq(Tarjeta.CODIGO, codigo.trim()));
		}

		if (numPlaca != null && numPlaca.trim().length() > 0) {
			c.add(Restrictions.eq(Tarjeta.NUM_PLACA, numPlaca.trim()));
		}

		List<?> l = c.add(Restrictions.eq(Tarjeta.ACTIVO, true)).addOrder(
				Order.asc(Tarjeta.ID)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).setMaxResults(1).list();

		Tarjeta tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = (Tarjeta) l.get(0);
			if (tmp != null) {
				log.debug("Tarjeta : " + tmp.toString());
			} else {
				log.debug("Tarjeta no encontrada");
			}
		}

		log
				.info("Fin - obtenerPorCodigoONumPlaca(String codigo, String numPlaca)");

		return tmp;
	}
}// TarjetaLayerImpl